using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Xml;
using MacomberMap.Common.Types;
using MacomberMap.Common.Components;
using System.ComponentModel;
using MacomberMap.Common.User_Interfaces.Components;
using System.Drawing;
using System.Data.Common;
using MacomberMap.Common.Events;

namespace MacomberMap.Common.Internals
{
    /// <summary>
    /// This class holds information on log events, including type, information to be logged, etc.
    /// </summary>
    public class MM_Event_Type : MM_Element
    {
        #region Variable declarations
        /// <summary>The type of event (e.g., warning, error)</summary>
        public EventLogEntryType EventType;

        /// <summary>The index of the event</summary>
        public int Index;

        /// <summary>The parameters needed to create this event</summary>
        public Dictionary<String, Type> Parameters;

      

        /// <summary>The collection of events of this particular type</summary>
        public Dictionary<UInt64, MM_Event> Events;

        /// <summary>
        /// The conditions under which an event is displayed
        /// </summary>
        public enum DisplayModeEnum { 
            /// <summary>Always display the event</summary>
            Always,
            /// <summary>Display the event when it's selected</summary>
            WhenSelected,
            /// <summary>Never display the event</summary>
            Never};

        /// <summary>
        /// The priority of the alarm
        /// </summary>
        [Category("Prioritization"), Description("The priority of the alarm")]
        public int Priority
        {
            get { return _Priority; }
            set { _Priority = value; }
        }
        private int _Priority;

        /// <summary>
        /// The acronym for the Event type
        /// </summary>
        [Category("Display"), Description("The acronym for the Event type")]
        public String Acronym
        {
            get { return _Acronym; }
            set { _Acronym = value; }
        }
        private String _Acronym;

        /// <summary>
        /// How the Event should be displayed in the mini-map
        /// </summary>
        [Category("Visibility"), Description("How the Event should be displayed in the mini-map"), DefaultValue(MM_Event_Type.DisplayModeEnum.WhenSelected)]
        public DisplayModeEnum MiniMap
        {
            get { return _MiniMap; }
            set { _MiniMap = value; }
        }
        private DisplayModeEnum _MiniMap = DisplayModeEnum.WhenSelected;


        /// <summary>
        /// Whether the Event type should be shown by its substation
        /// </summary>
        [Category("Visibility"), Description("Whether the Event type should be shown by its substation"), DefaultValue(MM_Event_Type.DisplayModeEnum.WhenSelected)]
        public DisplayModeEnum NetworkMap_Substation
        {
            get { return _Substation; }
            set { _Substation = value; }
        }
        private DisplayModeEnum _Substation = DisplayModeEnum.WhenSelected;


        /// <summary>
        /// Whether the Event type should be shown by its Line
        /// </summary>
        [Category("Visibility"), Description("Whether the Event type should be shown by its Line"), DefaultValue(MM_Event_Type.DisplayModeEnum.WhenSelected)]
        public DisplayModeEnum NetworkMap_Line
        {
            get { return _Line; }
            set { _Line = value; }
        }
        private DisplayModeEnum _Line = DisplayModeEnum.WhenSelected;

        /// <summary>
        /// How the Event type should be displayed in the Event viewer
        /// </summary>
        [Category("Visibility"), Description("How the Event type should be displayed in the Event viewer"), DefaultValue(DisplayModeEnum.WhenSelected)]
        public DisplayModeEnum EventViewer
        {
            get { return _EventViewer; }
            set { _EventViewer = value; }
        }
        private DisplayModeEnum _EventViewer = DisplayModeEnum.WhenSelected;

        /// <summary>
        /// Whether the Event is on in the Event viewer by default
        /// </summary>
        [Category("Visibility"), Description("Whether the Event is on in the Event viewer by default"), DefaultValue(true)]
        public bool EventViewerDefault
        {
            get { return _EventViewerDefault; }
            set { _EventViewerDefault = value; }
        }
        private bool _EventViewerDefault = true;

        /// <summary>
        /// Whether the Event type should be shown in a one-line diagram
        /// </summary>
        [Category("Visibility"), Description("Whether the Event type should be shown in a one-line diagram"), DefaultValue(MM_Event_Type.DisplayModeEnum.WhenSelected)]
        public DisplayModeEnum OneLineElement
        {
            get { return _OneLineElement; }
            set { _OneLineElement = value; }
        }
        private DisplayModeEnum _OneLineElement = DisplayModeEnum.WhenSelected;

        /// <summary>
        /// The image shown by the Event
        /// </summary>
        public Bitmap EventImage
        {
            get
            {
                return (Bitmap)MM_Overall_Display.EventImages.Images[this.Name];
            }
            set
            {
                if (value == null)
                    return;
                else
                    MM_Overall_Display.EventImages.Images[this.Index] = value;
            }
        }

        /// <summary>
        /// Whether this event type is permitted
        /// </summary>
        public new bool Permitted
        {
            get { return _Permitted; }
            set { _Permitted = value; }
        }
        private bool _Permitted;
        /// <summary>
        /// The foreground color of this event
        /// </summary>
        [Category("Display"), Description("The foreground color of this event")]
        public Color ForeColor
        {
            get { return _ForeColor; }
            set { _ForeColor = value; }
        }
        private Color _ForeColor;

        /// <summary>The thickness of elements with this event</summary>
        [Category("Display"), Description("The thickness of elements with this event"), DefaultValue(1)]
        public float Thickness
        {
            get { return _Thickness; }
            set { _Thickness = value; }
        }
        private float _Thickness;

        /// <summary>Whether elements with this event should blink</summary>
        [Category("Display"), Description("Whether elements with this event should blink"), DefaultValue(false)]
        public bool Blink
        {
            get { return _Blink; }
            set { _Blink = value; }
        }
        private bool _Blink;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize a new log event
        /// </summary>
        /// <param name="BaseElement">The base element defining this event</param>
        public MM_Event_Type(XmlElement BaseElement)
            : base(BaseElement)
        {
            this.EventType = (EventLogEntryType)Enum.Parse(typeof(EventLogEntryType), BaseElement.Attributes["EventType"].Value);
            this.Index = XmlConvert.ToInt32(BaseElement.Attributes["Index"].Value);
            Parameters = new Dictionary<string, Type>(BaseElement.ChildNodes.Count);
            foreach (XmlElement xParam in BaseElement.ChildNodes)
                Parameters.Add(xParam.Attributes["Name"].Value, MM_Type_Finder.LocateType(xParam.Attributes["Type"].Value, null));
            RebuildEventGraphic();
        }

        /// <summary>
        /// Initialize a new event type
        /// </summary>
        /// <param name="EventName">The name of the event type</param>
        public MM_Event_Type(String EventName)
        {
            this.Name = EventName;
            this.Acronym = EventName.Substring(0,3);
            RebuildEventGraphic();
        }

        /// <summary>
        /// Initialize a new log event
        /// </summary>
        /// <param name="DbReader">The database row defining this event</param>
        public MM_Event_Type(DbDataReader DbReader)
            : base(DbReader)
        {
            this.EventType = EventLogEntryType.Error;
            this.Index = Convert.ToInt32(DbReader["Index"]);
            this.Name = Convert.ToString(DbReader["Name"]);            

            XmlDocument xDoc = new XmlDocument();
            xDoc.LoadXml(Convert.ToString(DbReader["EventParameters"]));
            XmlElement BaseElement = xDoc.DocumentElement;
            Parameters = new Dictionary<string, Type>(BaseElement.ChildNodes.Count);            
            foreach (XmlElement xParam in BaseElement.ChildNodes)
                Parameters.Add(xParam.Attributes["Name"].Value, MM_Type_Finder.LocateType(xParam.Attributes["Type"].Value, null));
            RebuildEventGraphic();
        }
        /// <summary>
        /// Rebuild the graphic for a Event when its color changes
        /// </summary>       
        public void RebuildEventGraphic()
        {
            Bitmap b = new Bitmap(16, 16, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            Graphics g = Graphics.FromImage(b);
            StringFormat sF = new StringFormat();
            sF.Alignment = StringAlignment.Center;
            sF.LineAlignment = StringAlignment.Center;
            sF.Trimming = StringTrimming.None;
            sF.FormatFlags = StringFormatFlags.NoWrap;

            int ColorBrightness = ((ForeColor.R * 299) + (ForeColor.G * 587) + (ForeColor.B * 114)) / 1000;

            Color TextColor = (ColorBrightness >= 96 ? Color.FromArgb(32, 32, 32) : Color.FromArgb(223, 223, 223));
            g.Clear(ForeColor);
            g.DrawString(_Acronym, new Font("Arial", 8, FontStyle.Bold), new SolidBrush(TextColor), new RectangleF(0, 0, 16, 16), sF);
            g.Dispose();

            //First, update the display view's Event


            if (MM_Overall_Display.EventImages != null)
                if (MM_Overall_Display.EventImages.Images.ContainsKey(this.Name))
                {
                    MM_Overall_Display.EventImages.Images[this.Index] = b;
                    MM_Overall_Display.EventImages.Images.SetKeyName(this.Index, this.Name);
                }
                else
                {
                    MM_Overall_Display.EventImages.Images.Add(this.Name, b);
                    this.Index = MM_Overall_Display.EventImages.Images.Count - 1;
                }
        }
        #endregion

        #region Information
        /// <summary>
        /// Return the name of the Event type
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Name + " (" + Acronym + "; " + Index.ToString() + ")";
        }
        #endregion
    }
}
